package dao

import (
	"OJCenter/dao/mysql"
	"OJCenter/dao/redis"
	"OJCenter/global"
	"OJCenter/idl"
	"encoding/json"
	"errors"
	"strconv"
	"xorm.io/xorm"
)

const NoticeInfoPre = "n:"

type NoticeInfo struct {
	mysql *mysql.MysqlDao
	redis *redis.RedisDao
}

func NewNoticeInfo() (*NoticeInfo, error) {
	m, err := mysql.NewMysqlDao()
	if err != nil {
		return nil, err
	}
	r, err := redis.NewRedisDao()
	if err != nil {
		return nil, err
	}
	return &NoticeInfo{
		mysql: m,
		redis: r,
	}, nil
}

func (u *NoticeInfo) GetNoticeInfo(nid int64) (*idl.Notice, error) {
	var notice idl.Notice
	PInfoJson, err := u.redis.GetString(NoticeInfoPre + strconv.Itoa(int(nid)))
	if err != nil {
		_, err := u.mysql.Orm.Where("nid=?", nid).Get(&notice)
		if err != nil {
			return nil, err
		}

		j, _ := json.Marshal(notice)
		err = u.redis.SetString(NoticeInfoPre+strconv.Itoa(int(nid)), string(j), u.redis.TTL)
		if err != nil {
			global.Logger.Errorf("Notice load redis failed,err:%v", err)
		}
		return &notice, nil
	}
	err = json.Unmarshal([]byte(PInfoJson), &notice)
	if err != nil {
		global.Logger.Errorf("GetNoticeInfo unmarshal failed,err:%v", err)
	}
	return &notice, nil
}

func (u *NoticeInfo) DeleteNoticeInfo(info *idl.Notice) error {
	if info == nil {
		return errors.New("info is nil")
	}
	_, err := u.redis.DelKey(NoticeInfoPre + strconv.Itoa(int(info.Cid)))
	if err != nil {
		global.Logger.Errorf("Notice load redis failed,err:%v", err)
	}
	cond := make(map[string]interface{})
	cond["nid"] = info.Cid
	sum, err := u.mysql.DeleteInfos("notice", &cond)
	if err != nil || sum == 0 {
		return errors.New("delete Notice failed")
	}
	return nil
}

func (u *NoticeInfo) UpdateNoticeInfo(info map[string]interface{}) error {
	if info == nil {
		return errors.New("info is nil")
	}
	_, err := u.redis.DelKey(NoticeInfoPre + strconv.Itoa(int(info["nid"].(int64))))
	if err != nil {
		global.Logger.Errorf("Notice load redis failed,err:%v", err)
	}
	cond := make(map[string]interface{})
	cond["nid"] = info["nid"].(int64)
	sum, err := u.mysql.UpdateInfos("notice", &info, &cond)
	if err != nil || sum == 0 {
		return errors.New("update Notice failed")
	}
	return nil
}

func (u *NoticeInfo) InsertNoticeInfo(info *idl.Notice) error {
	Notice, err := u.GetNoticeInfo(info.Cid)
	if err != xorm.ErrNotExist {
		return err
	}
	sum, err := u.mysql.InsertInfos("notice", Notice)
	if err != nil || sum == 0 {
		return err
	}
	return nil
}

func (u *NoticeInfo) GetNoticeList(page int, limit int) (*[]idl.Notice, error) {
	var notices []idl.Notice
	err := u.mysql.Orm.Limit(limit, (page-1)*limit).Find(&notices)
	if err != nil {
		return nil, err
	}
	return &notices, nil
}

func (u *NoticeInfo) SelectNotice(info *idl.Notice) (*[]idl.Notice, error) {
	var rets []idl.Notice
	err := u.mysql.Orm.Table("problem").Find(&rets, info)
	if err != nil {
		return nil, err
	}
	return &rets, nil
}
